home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume10 / xlisp21 / part07 < prev    next >
Encoding:
Text File  |  1990-02-26  |  57.4 KB  |  2,513 lines

  1. Newsgroups: comp.sources.misc
  2. organization: Cognos Inc., Ottawa, Canada
  3. subject: v10i094: XLisP 2.1 sources 4a (1/2) / 5
  4. From: garym@cognos.UUCP (Gary Murphy)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 10, Issue 94
  8. Submitted-by: garym@cognos.UUCP (Gary Murphy)
  9. Archive-name: xlisp21/part07
  10.  
  11. #!/bin/sh
  12. # This is a shell archive, meaning:
  13. # 1. Remove everything above the #!/bin/sh line.
  14. # 2. Save the resulting text in a file.
  15. # 3. Execute the file with /bin/sh (not csh) to create the files:
  16. #    xljump.c
  17. #    xllist.c
  18. #    xlmath.c
  19. #    xlobj.c
  20. #    xlpp.c
  21. #    xlprin.c
  22. # This archive created: Sun Feb 18 23:40:11 1990
  23. # By:    Gary Murphy ()
  24. export PATH; PATH=/bin:$PATH
  25. echo shar: extracting "'xljump.c'" '(3889 characters)'
  26. if test -f 'xljump.c'
  27. then
  28.     echo shar: over-writing existing file "'xljump.c'"
  29. fi
  30. sed 's/^X//' << \SHAR_EOF > 'xljump.c'
  31. X/* xljump - execution context routines */
  32. X/*    Copyright (c) 1985, by David Michael Betz
  33. X    All Rights Reserved
  34. X    Permission is granted for unrestricted non-commercial use    */
  35. X
  36. X#include "xlisp.h"
  37. X
  38. X/* external variables */
  39. Xextern CONTEXT *xlcontext,*xltarget;
  40. Xextern LVAL xlvalue,xlenv,xlfenv,xldenv;
  41. Xextern int xlmask;
  42. X
  43. X/* xlbegin - beginning of an execution context */
  44. Xxlbegin(cptr,flags,expr)
  45. X  CONTEXT *cptr; int flags; LVAL expr;
  46. X{
  47. X    cptr->c_flags = flags;
  48. X    cptr->c_expr = expr;
  49. X    cptr->c_xlstack = xlstack;
  50. X    cptr->c_xlenv = xlenv;
  51. X    cptr->c_xlfenv = xlfenv;
  52. X    cptr->c_xldenv = xldenv;
  53. X    cptr->c_xlcontext = xlcontext;
  54. X    cptr->c_xlargv = xlargv;
  55. X    cptr->c_xlargc = xlargc;
  56. X    cptr->c_xlfp = xlfp;
  57. X    cptr->c_xlsp = xlsp;
  58. X    xlcontext = cptr;
  59. X}
  60. X
  61. X/* xlend - end of an execution context */
  62. Xxlend(cptr)
  63. X  CONTEXT *cptr;
  64. X{
  65. X    xlcontext = cptr->c_xlcontext;
  66. X}
  67. X
  68. X/* xlgo - go to a label */
  69. Xxlgo(label)
  70. X  LVAL label;
  71. X{
  72. X    CONTEXT *cptr;
  73. X    LVAL *argv;
  74. X    int argc;
  75. X
  76. X    /* find a tagbody context */
  77. X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
  78. X    if (cptr->c_flags & CF_GO) {
  79. X        argc = cptr->c_xlargc;
  80. X        argv = cptr->c_xlargv;
  81. X        while (--argc >= 0)
  82. X        if (*argv++ == label) {
  83. X            cptr->c_xlargc = argc;
  84. X            cptr->c_xlargv = argv;
  85. X            xljump(cptr,CF_GO,NIL);
  86. X        }
  87. X    }
  88. X    xlfail("no target for GO");
  89. X}
  90. X
  91. X/* xlreturn - return from a block */
  92. Xxlreturn(name,val)
  93. X  LVAL name,val;
  94. X{
  95. X    CONTEXT *cptr;
  96. X
  97. X    /* find a block context */
  98. X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
  99. X    if (cptr->c_flags & CF_RETURN && cptr->c_expr == name)
  100. X        xljump(cptr,CF_RETURN,val);
  101. X    xlfail("no target for RETURN");
  102. X}
  103. X
  104. X/* xlthrow - throw to a catch */
  105. Xxlthrow(tag,val)
  106. X  LVAL tag,val;
  107. X{
  108. X    CONTEXT *cptr;
  109. X
  110. X    /* find a catch context */
  111. X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
  112. X    if ((cptr->c_flags & CF_THROW) && cptr->c_expr == tag)
  113. X        xljump(cptr,CF_THROW,val);
  114. X    xlfail("no target for THROW");
  115. X}
  116. X
  117. X/* xlsignal - signal an error */
  118. Xxlsignal(emsg,arg)
  119. X  char *emsg; LVAL arg;
  120. X{
  121. X    CONTEXT *cptr;
  122. X
  123. X    /* find an error catcher */
  124. X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
  125. X    if (cptr->c_flags & CF_ERROR) {
  126. X        if (cptr->c_expr && emsg)
  127. X        xlerrprint("error",NULL,emsg,arg);
  128. X        xljump(cptr,CF_ERROR,NIL);
  129. X    }
  130. X}
  131. X
  132. X/* xltoplevel - go back to the top level */
  133. Xxltoplevel()
  134. X{
  135. X    stdputstr("[ back to top level ]\n");
  136. X    findandjump(CF_TOPLEVEL,"no top level");
  137. X}
  138. X
  139. X/* xlbrklevel - go back to the previous break level */
  140. Xxlbrklevel()
  141. X{
  142. X    findandjump(CF_BRKLEVEL,"no previous break level");
  143. X}
  144. X
  145. X/* xlcleanup - clean-up after an error */
  146. Xxlcleanup()
  147. X{
  148. X    stdputstr("[ back to previous break level ]\n");
  149. X    findandjump(CF_CLEANUP,"not in a break loop");
  150. X}
  151. X
  152. X/* xlcontinue - continue from an error */
  153. Xxlcontinue()
  154. X{
  155. X    findandjump(CF_CONTINUE,"not in a break loop");
  156. X}
  157. X
  158. X/* xljump - jump to a saved execution context */
  159. Xxljump(target,mask,val)
  160. X  CONTEXT *target; int mask; LVAL val;
  161. X{
  162. X    /* unwind the execution stack */
  163. X    for (; xlcontext != target; xlcontext = xlcontext->c_xlcontext)
  164. X
  165. X    /* check for an UNWIND-PROTECT */
  166. X    if ((xlcontext->c_flags & CF_UNWIND)) {
  167. X        xltarget = target;
  168. X        xlmask = mask;
  169. X        break;
  170. X    }
  171. X       
  172. X    /* restore the state */
  173. X    xlstack = xlcontext->c_xlstack;
  174. X    xlenv = xlcontext->c_xlenv;
  175. X    xlfenv = xlcontext->c_xlfenv;
  176. X    xlunbind(xlcontext->c_xldenv);
  177. X    xlargv = xlcontext->c_xlargv;
  178. X    xlargc = xlcontext->c_xlargc;
  179. X    xlfp = xlcontext->c_xlfp;
  180. X    xlsp = xlcontext->c_xlsp;
  181. X    xlvalue = val;
  182. X
  183. X    /* call the handler */
  184. X    longjmp(xlcontext->c_jmpbuf,mask);
  185. X}
  186. X
  187. X/* findandjump - find a target context frame and jump to it */
  188. XLOCAL findandjump(mask,error)
  189. X  int mask; char *error;
  190. X{
  191. X    CONTEXT *cptr;
  192. X
  193. X    /* find a block context */
  194. X    for (cptr = xlcontext; cptr; cptr = cptr->c_xlcontext)
  195. X    if (cptr->c_flags & mask)
  196. X        xljump(cptr,mask,NIL);
  197. X    xlabort(error);
  198. X}
  199. X
  200. SHAR_EOF
  201. if test 3889 -ne "`wc -c 'xljump.c'`"
  202. then
  203.     echo shar: error transmitting "'xljump.c'" '(should have been 3889 characters)'
  204. fi
  205. echo shar: extracting "'xllist.c'" '(18761 characters)'
  206. if test -f 'xllist.c'
  207. then
  208.     echo shar: over-writing existing file "'xllist.c'"
  209. fi
  210. sed 's/^X//' << \SHAR_EOF > 'xllist.c'
  211. X/* xllist.c - xlisp built-in list functions */
  212. X/*    Copyright (c) 1985, by David Michael Betz
  213. X    All Rights Reserved
  214. X    Permission is granted for unrestricted non-commercial use    */
  215. X
  216. X#include "xlisp.h"
  217. X
  218. X/* forward declarations */
  219. XFORWARD LVAL cxr();
  220. XFORWARD LVAL nth(),assoc();
  221. XFORWARD LVAL subst(),sublis(),map();
  222. X
  223. X/* xcar - take the car of a cons cell */
  224. XLVAL xcar()
  225. X{
  226. X    LVAL list;
  227. X    list = xlgalist();
  228. X    xllastarg();
  229. X    return (list ? car(list) : NIL);
  230. X}
  231. X
  232. X/* xcdr - take the cdr of a cons cell */
  233. XLVAL xcdr()
  234. X{
  235. X    LVAL list;
  236. X    list = xlgalist();
  237. X    xllastarg();
  238. X    return (list ? cdr(list) : NIL);
  239. X}
  240. X
  241. X/* cxxr functions */
  242. XLVAL xcaar() { return (cxr("aa")); }
  243. XLVAL xcadr() { return (cxr("da")); }
  244. XLVAL xcdar() { return (cxr("ad")); }
  245. XLVAL xcddr() { return (cxr("dd")); }
  246. X
  247. X/* cxxxr functions */
  248. XLVAL xcaaar() { return (cxr("aaa")); }
  249. XLVAL xcaadr() { return (cxr("daa")); }
  250. XLVAL xcadar() { return (cxr("ada")); }
  251. XLVAL xcaddr() { return (cxr("dda")); }
  252. XLVAL xcdaar() { return (cxr("aad")); }
  253. XLVAL xcdadr() { return (cxr("dad")); }
  254. XLVAL xcddar() { return (cxr("add")); }
  255. XLVAL xcdddr() { return (cxr("ddd")); }
  256. X
  257. X/* cxxxxr functions */
  258. XLVAL xcaaaar() { return (cxr("aaaa")); }
  259. XLVAL xcaaadr() { return (cxr("daaa")); }
  260. XLVAL xcaadar() { return (cxr("adaa")); }
  261. XLVAL xcaaddr() { return (cxr("ddaa")); }
  262. XLVAL xcadaar() { return (cxr("aada")); }
  263. XLVAL xcadadr() { return (cxr("dada")); }
  264. XLVAL xcaddar() { return (cxr("adda")); }
  265. XLVAL xcadddr() { return (cxr("ddda")); }
  266. XLVAL xcdaaar() { return (cxr("aaad")); }
  267. XLVAL xcdaadr() { return (cxr("daad")); }
  268. XLVAL xcdadar() { return (cxr("adad")); }
  269. XLVAL xcdaddr() { return (cxr("ddad")); }
  270. XLVAL xcddaar() { return (cxr("aadd")); }
  271. XLVAL xcddadr() { return (cxr("dadd")); }
  272. XLVAL xcdddar() { return (cxr("addd")); }
  273. XLVAL xcddddr() { return (cxr("dddd")); }
  274. X
  275. X/* cxr - common car/cdr routine */
  276. XLOCAL LVAL cxr(adstr)
  277. X  char *adstr;
  278. X{
  279. X    LVAL list;
  280. X
  281. X    /* get the list */
  282. X    list = xlgalist();
  283. X    xllastarg();
  284. X
  285. X    /* perform the car/cdr operations */
  286. X    while (*adstr && consp(list))
  287. X    list = (*adstr++ == 'a' ? car(list) : cdr(list));
  288. X
  289. X    /* make sure the operation succeeded */
  290. X    if (*adstr && list)
  291. X    xlfail("bad argument");
  292. X
  293. X    /* return the result */
  294. X    return (list);
  295. X}
  296. X
  297. X/* xcons - construct a new list cell */
  298. XLVAL xcons()
  299. X{
  300. X    LVAL arg1,arg2;
  301. X
  302. X    /* get the two arguments */
  303. X    arg1 = xlgetarg();
  304. X    arg2 = xlgetarg();
  305. X    xllastarg();
  306. X
  307. X    /* construct a new list element */
  308. X    return (cons(arg1,arg2));
  309. X}
  310. X
  311. X/* xlist - built a list of the arguments */
  312. XLVAL xlist()
  313. X{
  314. X    LVAL last,next,val;
  315. X
  316. X    /* protect some pointers */
  317. X    xlsave1(val);
  318. X
  319. X    /* add each argument to the list */
  320. X    for (val = NIL; moreargs(); ) {
  321. X
  322. X    /* append this argument to the end of the list */
  323. X    next = consa(nextarg());
  324. X    if (val) rplacd(last,next);
  325. X    else val = next;
  326. X    last = next;
  327. X    }
  328. X
  329. X    /* restore the stack */
  330. X    xlpop();
  331. X
  332. X    /* return the list */
  333. X    return (val);
  334. X}
  335. X
  336. X/* xappend - built-in function append */
  337. XLVAL xappend()
  338. X{
  339. X    LVAL list,last,next,val;
  340. X
  341. X    /* protect some pointers */
  342. X    xlsave1(val);
  343. X
  344. X    /* initialize */
  345. X    val = NIL;
  346. X    
  347. X    /* append each argument */
  348. X    if (moreargs()) {
  349. X    while (xlargc > 1) {
  350. X
  351. X        /* append each element of this list to the result list */
  352. X        for (list = nextarg(); consp(list); list = cdr(list)) {
  353. X        next = consa(car(list));
  354. X        if (val) rplacd(last,next);
  355. X        else val = next;
  356. X        last = next;
  357. X        }
  358. X    }
  359. X
  360. X    /* handle the last argument */
  361. X    if (val) rplacd(last,nextarg());
  362. X    else val = nextarg();
  363. X    }
  364. X
  365. X    /* restore the stack */
  366. X    xlpop();
  367. X
  368. X    /* return the list */
  369. X    return (val);
  370. X}
  371. X
  372. X/* xreverse - built-in function reverse */
  373. XLVAL xreverse()
  374. X{
  375. X    LVAL list,val;
  376. X
  377. X    /* protect some pointers */
  378. X    xlsave1(val);
  379. X
  380. X    /* get the list to reverse */
  381. X    list = xlgalist();
  382. X    xllastarg();
  383. X
  384. X    /* append each element to the head of the result list */
  385. X    for (val = NIL; consp(list); list = cdr(list))
  386. X    val = cons(car(list),val);
  387. X
  388. X    /* restore the stack */
  389. X    xlpop();
  390. X
  391. X    /* return the list */
  392. X    return (val);
  393. X}
  394. X
  395. X/* xlast - return the last cons of a list */
  396. XLVAL xlast()
  397. X{
  398. X    LVAL list;
  399. X
  400. X    /* get the list */
  401. X    list = xlgalist();
  402. X    xllastarg();
  403. X
  404. X    /* find the last cons */
  405. X    while (consp(list) && cdr(list))
  406. X    list = cdr(list);
  407. X
  408. X    /* return the last element */
  409. X    return (list);
  410. X}
  411. X
  412. X/* xmember - built-in function 'member' */
  413. XLVAL xmember()
  414. X{
  415. X    LVAL x,list,fcn,val;
  416. X    int tresult;
  417. X
  418. X    /* protect some pointers */
  419. X    xlsave1(fcn);
  420. X
  421. X    /* get the expression to look for and the list */
  422. X    x = xlgetarg();
  423. X    list = xlgalist();
  424. X    xltest(&fcn,&tresult);
  425. X
  426. X    /* look for the expression */
  427. X    for (val = NIL; consp(list); list = cdr(list))
  428. X    if (dotest2(x,car(list),fcn) == tresult) {
  429. X        val = list;
  430. X        break;
  431. X    }
  432. X
  433. X    /* restore the stack */
  434. X    xlpop();
  435. X
  436. X    /* return the result */
  437. X    return (val);
  438. X}
  439. X
  440. X/* xassoc - built-in function 'assoc' */
  441. XLVAL xassoc()
  442. X{
  443. X    LVAL x,alist,fcn,pair,val;
  444. X    int tresult;
  445. X
  446. X    /* protect some pointers */
  447. X    xlsave1(fcn);
  448. X
  449. X    /* get the expression to look for and the association list */
  450. X    x = xlgetarg();
  451. X    alist = xlgalist();
  452. X    xltest(&fcn,&tresult);
  453. X
  454. X    /* look for the expression */
  455. X    for (val = NIL; consp(alist); alist = cdr(alist))
  456. X    if ((pair = car(alist)) && consp(pair))
  457. X        if (dotest2(x,car(pair),fcn) == tresult) {
  458. X        val = pair;
  459. X        break;
  460. X        }
  461. X
  462. X    /* restore the stack */
  463. X    xlpop();
  464. X
  465. X    /* return result */
  466. X    return (val);
  467. X}
  468. X
  469. X/* xsubst - substitute one expression for another */
  470. XLVAL xsubst()
  471. X{
  472. X    LVAL to,from,expr,fcn,val;
  473. X    int tresult;
  474. X
  475. X    /* protect some pointers */
  476. X    xlsave1(fcn);
  477. X
  478. X    /* get the to value, the from value and the expression */
  479. X    to = xlgetarg();
  480. X    from = xlgetarg();
  481. X    expr = xlgetarg();
  482. X    xltest(&fcn,&tresult);
  483. X
  484. X    /* do the substitution */
  485. X    val = subst(to,from,expr,fcn,tresult);
  486. X
  487. X    /* restore the stack */
  488. X    xlpop();
  489. X
  490. X    /* return the result */
  491. X    return (val);
  492. X}
  493. X
  494. X/* subst - substitute one expression for another */
  495. XLOCAL LVAL subst(to,from,expr,fcn,tresult)
  496. X  LVAL to,from,expr,fcn; int tresult;
  497. X{
  498. X    LVAL carval,cdrval;
  499. X
  500. X    if (dotest2(expr,from,fcn) == tresult)
  501. X    return (to);
  502. X    else if (consp(expr)) {
  503. X    xlsave1(carval);
  504. X    carval = subst(to,from,car(expr),fcn,tresult);
  505. X    cdrval = subst(to,from,cdr(expr),fcn,tresult);
  506. X    xlpop();
  507. X    return (cons(carval,cdrval));
  508. X    }
  509. X    else
  510. X    return (expr);
  511. X}
  512. X
  513. X/* xsublis - substitute using an association list */
  514. XLVAL xsublis()
  515. X{
  516. X    LVAL alist,expr,fcn,val;
  517. X    int tresult;
  518. X
  519. X    /* protect some pointers */
  520. X    xlsave1(fcn);
  521. X
  522. X    /* get the assocation list and the expression */
  523. X    alist = xlgalist();
  524. X    expr = xlgetarg();
  525. X    xltest(&fcn,&tresult);
  526. X
  527. X    /* do the substitution */
  528. X    val = sublis(alist,expr,fcn,tresult);
  529. X
  530. X    /* restore the stack */
  531. X    xlpop();
  532. X
  533. X    /* return the result */
  534. X    return (val);
  535. X}
  536. X
  537. X/* sublis - substitute using an association list */
  538. XLOCAL LVAL sublis(alist,expr,fcn,tresult)
  539. X  LVAL alist,expr,fcn; int tresult;
  540. X{
  541. X    LVAL carval,cdrval,pair;
  542. X
  543. X    if (pair = assoc(expr,alist,fcn,tresult))
  544. X    return (cdr(pair));
  545. X    else if (consp(expr)) {
  546. X    xlsave1(carval);
  547. X    carval = sublis(alist,car(expr),fcn,tresult);
  548. X    cdrval = sublis(alist,cdr(expr),fcn,tresult);
  549. X    xlpop();
  550. X    return (cons(carval,cdrval));
  551. X    }
  552. X    else
  553. X    return (expr);
  554. X}
  555. X
  556. X/* assoc - find a pair in an association list */
  557. XLOCAL LVAL assoc(expr,alist,fcn,tresult)
  558. X  LVAL expr,alist,fcn; int tresult;
  559. X{
  560. X    LVAL pair;
  561. X
  562. X    for (; consp(alist); alist = cdr(alist))
  563. X    if ((pair = car(alist)) && consp(pair))
  564. X        if (dotest2(expr,car(pair),fcn) == tresult)
  565. X        return (pair);
  566. X    return (NIL);
  567. X}
  568. X
  569. X/* xremove - built-in function 'remove' */
  570. XLVAL xremove()
  571. X{
  572. X    LVAL x,list,fcn,val,last,next;
  573. X    int tresult;
  574. X
  575. X    /* protect some pointers */
  576. X    xlstkcheck(2);
  577. X    xlsave(fcn);
  578. X    xlsave(val);
  579. X
  580. X    /* get the expression to remove and the list */
  581. X    x = xlgetarg();
  582. X    list = xlgalist();
  583. X    xltest(&fcn,&tresult);
  584. X
  585. X    /* remove matches */
  586. X    for (; consp(list); list = cdr(list))
  587. X
  588. X    /* check to see if this element should be deleted */
  589. X    if (dotest2(x,car(list),fcn) != tresult) {
  590. X        next = consa(car(list));
  591. X        if (val) rplacd(last,next);
  592. X        else val = next;
  593. X        last = next;
  594. X    }
  595. X
  596. X    /* restore the stack */
  597. X    xlpopn(2);
  598. X
  599. X    /* return the updated list */
  600. X    return (val);
  601. X}
  602. X
  603. X/* xremif - built-in function 'remove-if' */
  604. XLVAL xremif()
  605. X{
  606. X    LVAL remif();
  607. X    return (remif(TRUE));
  608. X}
  609. X
  610. X/* xremifnot - built-in function 'remove-if-not' */
  611. XLVAL xremifnot()
  612. X{
  613. X    LVAL remif();
  614. X    return (remif(FALSE));
  615. X}
  616. X
  617. X/* remif - common code for 'remove-if' and 'remove-if-not' */
  618. XLOCAL LVAL remif(tresult)
  619. X  int tresult;
  620. X{
  621. X    LVAL list,fcn,val,last,next;
  622. X
  623. X    /* protect some pointers */
  624. X    xlstkcheck(2);
  625. X    xlsave(fcn);
  626. X    xlsave(val);
  627. X
  628. X    /* get the expression to remove and the list */
  629. X    fcn = xlgetarg();
  630. X    list = xlgalist();
  631. X    xllastarg();
  632. X
  633. X    /* remove matches */
  634. X    for (; consp(list); list = cdr(list))
  635. X
  636. X    /* check to see if this element should be deleted */
  637. X    if (dotest1(car(list),fcn) != tresult) {
  638. X        next = consa(car(list));
  639. X        if (val) rplacd(last,next);
  640. X        else val = next;
  641. X        last = next;
  642. X    }
  643. X
  644. X    /* restore the stack */
  645. X    xlpopn(2);
  646. X
  647. X    /* return the updated list */
  648. X    return (val);
  649. X}
  650. X
  651. X/* dotest1 - call a test function with one argument */
  652. Xint dotest1(arg,fun)
  653. X  LVAL arg,fun;
  654. X{
  655. X    LVAL *newfp;
  656. X
  657. X    /* create the new call frame */
  658. X    newfp = xlsp;
  659. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  660. X    pusharg(fun);
  661. X    pusharg(cvfixnum((FIXTYPE)1));
  662. X    pusharg(arg);
  663. X    xlfp = newfp;
  664. X
  665. X    /* return the result of applying the test function */
  666. X    return (xlapply(1) != NIL);
  667. X
  668. X}
  669. X
  670. X/* dotest2 - call a test function with two arguments */
  671. Xint dotest2(arg1,arg2,fun)
  672. X  LVAL arg1,arg2,fun;
  673. X{
  674. X    LVAL *newfp;
  675. X
  676. X    /* create the new call frame */
  677. X    newfp = xlsp;
  678. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  679. X    pusharg(fun);
  680. X    pusharg(cvfixnum((FIXTYPE)2));
  681. X    pusharg(arg1);
  682. X    pusharg(arg2);
  683. X    xlfp = newfp;
  684. X
  685. X    /* return the result of applying the test function */
  686. X    return (xlapply(2) != NIL);
  687. X
  688. X}
  689. X
  690. X/* xnth - return the nth element of a list */
  691. XLVAL xnth()
  692. X{
  693. X    return (nth(TRUE));
  694. X}
  695. X
  696. X/* xnthcdr - return the nth cdr of a list */
  697. XLVAL xnthcdr()
  698. X{
  699. X    return (nth(FALSE));
  700. X}
  701. X
  702. X/* nth - internal nth function */
  703. XLOCAL LVAL nth(carflag)
  704. X  int carflag;
  705. X{
  706. X    LVAL list,num;
  707. X    FIXTYPE n;
  708. X
  709. X    /* get n and the list */
  710. X    num = xlgafixnum();
  711. X    list = xlgacons();
  712. X    xllastarg();
  713. X
  714. X    /* make sure the number isn't negative */
  715. X    if ((n = getfixnum(num)) < 0)
  716. X    xlfail("bad argument");
  717. X
  718. X    /* find the nth element */
  719. X    while (consp(list) && --n >= 0)
  720. X    list = cdr(list);
  721. X
  722. X    /* return the list beginning at the nth element */
  723. X    return (carflag && consp(list) ? car(list) : list);
  724. X}
  725. X
  726. X/* xlength - return the length of a list or string */
  727. XLVAL xlength()
  728. X{
  729. X    FIXTYPE n;
  730. X    LVAL arg;
  731. X
  732. X    /* get the list or string */
  733. X    arg = xlgetarg();
  734. X    xllastarg();
  735. X
  736. X    /* find the length of a list */
  737. X    if (listp(arg))
  738. X    for (n = 0; consp(arg); n++)
  739. X        arg = cdr(arg);
  740. X
  741. X    /* find the length of a string */
  742. X    else if (stringp(arg))
  743. X    n = (FIXTYPE)getslength(arg)-1;
  744. X
  745. X    /* find the length of a vector */
  746. X    else if (vectorp(arg))
  747. X    n = (FIXTYPE)getsize(arg);
  748. X
  749. X    /* otherwise, bad argument type */
  750. X    else
  751. X    xlerror("bad argument type",arg);
  752. X
  753. X    /* return the length */
  754. X    return (cvfixnum(n));
  755. X}
  756. X
  757. X/* xmapc - built-in function 'mapc' */
  758. XLVAL xmapc()
  759. X{
  760. X    return (map(TRUE,FALSE));
  761. X}
  762. X
  763. X/* xmapcar - built-in function 'mapcar' */
  764. XLVAL xmapcar()
  765. X{
  766. X    return (map(TRUE,TRUE));
  767. X}
  768. X
  769. X/* xmapl - built-in function 'mapl' */
  770. XLVAL xmapl()
  771. X{
  772. X    return (map(FALSE,FALSE));
  773. X}
  774. X
  775. X/* xmaplist - built-in function 'maplist' */
  776. XLVAL xmaplist()
  777. X{
  778. X    return (map(FALSE,TRUE));
  779. X}
  780. X
  781. X/* map - internal mapping function */
  782. XLOCAL LVAL map(carflag,valflag)
  783. X  int carflag,valflag;
  784. X{
  785. X    LVAL *newfp,fun,lists,val,last,p,x,y;
  786. X    int argc;
  787. X
  788. X    /* protect some pointers */
  789. X    xlstkcheck(3);
  790. X    xlsave(fun);
  791. X    xlsave(lists);
  792. X    xlsave(val);
  793. X
  794. X    /* get the function to apply and the first list */
  795. X    fun = xlgetarg();
  796. X    lists = xlgalist();
  797. X
  798. X    /* initialize the result list */
  799. X    val = (valflag ? NIL : lists);
  800. X
  801. X    /* build a list of argument lists */
  802. X    for (lists = last = consa(lists); moreargs(); last = cdr(last))
  803. X    rplacd(last,cons(xlgalist(),NIL));
  804. X
  805. X    /* loop through each of the argument lists */
  806. X    for (;;) {
  807. X
  808. X    /* build an argument list from the sublists */
  809. X    newfp = xlsp;
  810. X    pusharg(cvfixnum((FIXTYPE)(newfp - xlfp)));
  811. X    pusharg(fun);
  812. X    pusharg(NIL);
  813. X    argc = 0;
  814. X    for (x = lists; x && (y = car(x)) && consp(y); x = cdr(x)) {
  815. X        pusharg(carflag ? car(y) : y);
  816. X        rplaca(x,cdr(y));
  817. X        ++argc;
  818. X    }
  819. X
  820. X    /* quit if any of the lists were empty */
  821. X    if (x) {
  822. X        xlsp = newfp;
  823. X        break;
  824. X    }
  825. X
  826. X    /* apply the function to the arguments */
  827. X    newfp[2] = cvfixnum((FIXTYPE)argc);
  828. X    xlfp = newfp;
  829. X    if (valflag) {
  830. X        p = consa(xlapply(argc));
  831. X        if (val) rplacd(last,p);
  832. X        else val = p;
  833. X        last = p;
  834. X    }
  835. X    else
  836. X        xlapply(argc);
  837. X    }
  838. X
  839. X    /* restore the stack */
  840. X    xlpopn(3);
  841. X
  842. X    /* return the last test expression value */
  843. X    return (val);
  844. X}
  845. X
  846. X/* xrplca - replace the car of a list node */
  847. XLVAL xrplca()
  848. X{
  849. X    LVAL list,newcar;
  850. X
  851. X    /* get the list and the new car */
  852. X    list = xlgacons();
  853. X    newcar = xlgetarg();
  854. X    xllastarg();
  855. X
  856. X    /* replace the car */
  857. X    rplaca(list,newcar);
  858. X
  859. X    /* return the list node that was modified */
  860. X    return (list);
  861. X}
  862. X
  863. X/* xrplcd - replace the cdr of a list node */
  864. XLVAL xrplcd()
  865. X{
  866. X    LVAL list,newcdr;
  867. X
  868. X    /* get the list and the new cdr */
  869. X    list = xlgacons();
  870. X    newcdr = xlgetarg();
  871. X    xllastarg();
  872. X
  873. X    /* replace the cdr */
  874. X    rplacd(list,newcdr);
  875. X
  876. X    /* return the list node that was modified */
  877. X    return (list);
  878. X}
  879. X
  880. X/* xnconc - destructively append lists */
  881. XLVAL xnconc()
  882. X{
  883. X    LVAL next,last,val;
  884. X
  885. X    /* initialize */
  886. X    val = NIL;
  887. X    
  888. X    /* concatenate each argument */
  889. X    if (moreargs()) {
  890. X    while (xlargc > 1) {
  891. X
  892. X        /* ignore everything except lists */
  893. X        if ((next = nextarg()) && consp(next)) {
  894. X
  895. X        /* concatenate this list to the result list */
  896. X        if (val) rplacd(last,next);
  897. X        else val = next;
  898. X
  899. X        /* find the end of the list */
  900. X        while (consp(cdr(next)))
  901. X            next = cdr(next);
  902. X        last = next;
  903. X        }
  904. X    }
  905. X
  906. X    /* handle the last argument */
  907. X    if (val) rplacd(last,nextarg());
  908. X    else val = nextarg();
  909. X    }
  910. X
  911. X    /* return the list */
  912. X    return (val);
  913. X}
  914. X
  915. X/* xdelete - built-in function 'delete' */
  916. XLVAL xdelete()
  917. X{
  918. X    LVAL x,list,fcn,last,val;
  919. X    int tresult;
  920. X
  921. X    /* protect some pointers */
  922. X    xlsave1(fcn);
  923. X
  924. X    /* get the expression to delete and the list */
  925. X    x = xlgetarg();
  926. X    list = xlgalist();
  927. X    xltest(&fcn,&tresult);
  928. X
  929. X    /* delete leading matches */
  930. X    while (consp(list)) {
  931. X    if (dotest2(x,car(list),fcn) != tresult)
  932. X        break;
  933. X    list = cdr(list);
  934. X    }
  935. X    val = last = list;
  936. X
  937. X    /* delete embedded matches */
  938. X    if (consp(list)) {
  939. X
  940. X    /* skip the first non-matching element */
  941. X    list = cdr(list);
  942. X
  943. X    /* look for embedded matches */
  944. X    while (consp(list)) {
  945. X
  946. X        /* check to see if this element should be deleted */
  947. X        if (dotest2(x,car(list),fcn) == tresult)
  948. X        rplacd(last,cdr(list));
  949. X        else
  950. X        last = list;
  951. X
  952. X        /* move to the next element */
  953. X        list = cdr(list);
  954. X     }
  955. X    }
  956. X
  957. X    /* restore the stack */
  958. X    xlpop();
  959. X
  960. X    /* return the updated list */
  961. X    return (val);
  962. X}
  963. X
  964. X/* xdelif - built-in function 'delete-if' */
  965. XLVAL xdelif()
  966. X{
  967. X    LVAL delif();
  968. X    return (delif(TRUE));
  969. X}
  970. X
  971. X/* xdelifnot - built-in function 'delete-if-not' */
  972. XLVAL xdelifnot()
  973. X{
  974. X    LVAL delif();
  975. X    return (delif(FALSE));
  976. X}
  977. X
  978. X/* delif - common routine for 'delete-if' and 'delete-if-not' */
  979. XLOCAL LVAL delif(tresult)
  980. X  int tresult;
  981. X{
  982. X    LVAL list,fcn,last,val;
  983. X
  984. X    /* protect some pointers */
  985. X    xlsave1(fcn);
  986. X
  987. X    /* get the expression to delete and the list */
  988. X    fcn = xlgetarg();
  989. X    list = xlgalist();
  990. X    xllastarg();
  991. X
  992. X    /* delete leading matches */
  993. X    while (consp(list)) {
  994. X    if (dotest1(car(list),fcn) != tresult)
  995. X        break;
  996. X    list = cdr(list);
  997. X    }
  998. X    val = last = list;
  999. X
  1000. X    /* delete embedded matches */
  1001. X    if (consp(list)) {
  1002. X
  1003. X    /* skip the first non-matching element */
  1004. X    list = cdr(list);
  1005. X
  1006. X    /* look for embedded matches */
  1007. X    while (consp(list)) {
  1008. X
  1009. X        /* check to see if this element should be deleted */
  1010. X        if (dotest1(car(list),fcn) == tresult)
  1011. X        rplacd(last,cdr(list));
  1012. X        else
  1013. X        last = list;
  1014. X
  1015. X        /* move to the next element */
  1016. X        list = cdr(list);
  1017. X     }
  1018. X    }
  1019. X
  1020. X    /* restore the stack */
  1021. X    xlpop();
  1022. X
  1023. X    /* return the updated list */
  1024. X    return (val);
  1025. X}
  1026. X
  1027. X/* xsort - built-in function 'sort' */
  1028. XLVAL xsort()
  1029. X{
  1030. X    LVAL sortlist();
  1031. X    LVAL list,fcn;
  1032. X
  1033. X    /* protect some pointers */
  1034. X    xlstkcheck(2);
  1035. X    xlsave(list);
  1036. X    xlsave(fcn);
  1037. X
  1038. X    /* get the list to sort and the comparison function */
  1039. X    list = xlgalist();
  1040. X    fcn = xlgetarg();
  1041. X    xllastarg();
  1042. X
  1043. X    /* sort the list */
  1044. X    list = sortlist(list,fcn);
  1045. X
  1046. X    /* restore the stack and return the sorted list */
  1047. X    xlpopn(2);
  1048. X    return (list);
  1049. X}
  1050. X
  1051. X/*
  1052. X    This sorting algorithm is based on a Modula-2 sort written by
  1053. X    Richie Bielak and published in the February 1988 issue of
  1054. X    "Computer Language" magazine in a letter to the editor.
  1055. X*/
  1056. X
  1057. X/* sortlist - sort a list using quicksort */
  1058. XLOCAL LVAL sortlist(list,fcn)
  1059. X  LVAL list,fcn;
  1060. X{
  1061. X    LVAL gluelists();
  1062. X    LVAL smaller,pivot,larger;
  1063. X    
  1064. X    /* protect some pointers */
  1065. X    xlstkcheck(3);
  1066. X    xlsave(smaller);
  1067. X    xlsave(pivot);
  1068. X    xlsave(larger);
  1069. X    
  1070. X    /* lists with zero or one element are already sorted */
  1071. X    if (consp(list) && consp(cdr(list))) {
  1072. X    pivot = list; list = cdr(list);
  1073. X    splitlist(pivot,list,&smaller,&larger,fcn);
  1074. X    smaller = sortlist(smaller,fcn);
  1075. X    larger = sortlist(larger,fcn);
  1076. X    list = gluelists(smaller,pivot,larger);
  1077. X    }
  1078. X
  1079. X    /* cleanup the stack and return the sorted list */
  1080. X    xlpopn(3);
  1081. X    return (list);
  1082. X}
  1083. X
  1084. X/* splitlist - split the list around the pivot */
  1085. XLOCAL splitlist(pivot,list,psmaller,plarger,fcn)
  1086. X  LVAL pivot,list,*psmaller,*plarger,fcn;
  1087. X{
  1088. X    LVAL next;
  1089. X    
  1090. X    /* initialize the result lists */
  1091. X    *psmaller = *plarger = NIL;
  1092. X    
  1093. X    /* split the list */
  1094. X    for (; consp(list); list = next) {
  1095. X    next = cdr(list);
  1096. X    if (dotest2(car(list),car(pivot),fcn)) {
  1097. X        rplacd(list,*psmaller);
  1098. X        *psmaller = list;
  1099. X    }
  1100. X    else {
  1101. X        rplacd(list,*plarger);
  1102. X        *plarger = list;
  1103. X    }
  1104. X    }
  1105. X}
  1106. X
  1107. X/* gluelists - glue the smaller and larger lists with the pivot */
  1108. XLOCAL LVAL gluelists(smaller,pivot,larger)
  1109. X  LVAL smaller,pivot,larger;
  1110. X{
  1111. X    LVAL last;
  1112. X    
  1113. X    /* larger always goes after the pivot */
  1114. X    rplacd(pivot,larger);
  1115. X
  1116. X    /* if the smaller list is empty, we're done */
  1117. X    if (null(smaller))
  1118. X    return (pivot);
  1119. X
  1120. X    /* append the smaller to the front of the resulting list */
  1121. X    for (last = smaller; consp(cdr(last)); last = cdr(last))
  1122. X    ;
  1123. X    rplacd(last,pivot);
  1124. X    return (smaller);
  1125. X}
  1126. SHAR_EOF
  1127. if test 18761 -ne "`wc -c 'xllist.c'`"
  1128. then
  1129.     echo shar: error transmitting "'xllist.c'" '(should have been 18761 characters)'
  1130. fi
  1131. echo shar: extracting "'xlmath.c'" '(9993 characters)'
  1132. if test -f 'xlmath.c'
  1133. then
  1134.     echo shar: over-writing existing file "'xlmath.c'"
  1135. fi
  1136. sed 's/^X//' << \SHAR_EOF > 'xlmath.c'
  1137. X/* xlmath - xlisp built-in arithmetic functions */
  1138. X/*    Copyright (c) 1985, by David Michael Betz
  1139. X    All Rights Reserved
  1140. X    Permission is granted for unrestricted non-commercial use    */
  1141. X
  1142. X#include "xlisp.h"
  1143. X#include <math.h>
  1144. X
  1145. X/* external variables */
  1146. Xextern LVAL true;
  1147. X
  1148. X/* forward declarations */
  1149. XFORWARD LVAL unary();
  1150. XFORWARD LVAL binary();
  1151. XFORWARD LVAL predicate();
  1152. XFORWARD LVAL compare();
  1153. X
  1154. X/* binary functions */
  1155. XLVAL xadd()    { return (binary('+')); } /* + */
  1156. XLVAL xsub()    { return (binary('-')); } /* - */
  1157. XLVAL xmul()    { return (binary('*')); } /* * */
  1158. XLVAL xdiv()    { return (binary('/')); } /* / */
  1159. XLVAL xrem()    { return (binary('%')); } /* rem */
  1160. XLVAL xmin()    { return (binary('m')); } /* min */
  1161. XLVAL xmax()    { return (binary('M')); } /* max */
  1162. XLVAL xexpt()   { return (binary('E')); } /* expt */
  1163. XLVAL xlogand() { return (binary('&')); } /* logand */
  1164. XLVAL xlogior() { return (binary('|')); } /* logior */
  1165. XLVAL xlogxor() { return (binary('^')); } /* logxor */
  1166. X
  1167. X/* xgcd - greatest common divisor */
  1168. XLVAL xgcd()
  1169. X{
  1170. X    FIXTYPE m,n,r;
  1171. X    LVAL arg;
  1172. X
  1173. X    if (!moreargs())            /* check for identity case */
  1174. X    return (cvfixnum((FIXTYPE)0));
  1175. X    arg = xlgafixnum();
  1176. X    n = getfixnum(arg);
  1177. X    if (n < (FIXTYPE)0) n = -n;        /* absolute value */
  1178. X    while (moreargs()) {
  1179. X    arg = xlgafixnum();
  1180. X    m = getfixnum(arg);
  1181. X    if (m < (FIXTYPE)0) m = -m;    /* absolute value */
  1182. X    for (;;) {            /* euclid's algorithm */
  1183. X        r = m % n;
  1184. X        if (r == (FIXTYPE)0)
  1185. X        break;
  1186. X        m = n;
  1187. X        n = r;
  1188. X    }
  1189. X    }
  1190. X    return (cvfixnum(n));
  1191. X}
  1192. X
  1193. X/* binary - handle binary operations */
  1194. XLOCAL LVAL binary(fcn)
  1195. X  int fcn;
  1196. X{
  1197. X    FIXTYPE ival,iarg;
  1198. X    FLOTYPE fval,farg;
  1199. X    LVAL arg;
  1200. X    int mode;
  1201. X
  1202. X    /* get the first argument */
  1203. X    arg = xlgetarg();
  1204. X
  1205. X    /* set the type of the first argument */
  1206. X    if (fixp(arg)) {
  1207. X    ival = getfixnum(arg);
  1208. X    mode = 'I';
  1209. X    }
  1210. X    else if (floatp(arg)) {
  1211. X    fval = getflonum(arg);
  1212. X    mode = 'F';
  1213. X    }
  1214. X    else
  1215. X    xlerror("bad argument type",arg);
  1216. X
  1217. X    /* treat a single argument as a special case */
  1218. X    if (!moreargs()) {
  1219. X    switch (fcn) {
  1220. X    case '-':
  1221. X        switch (mode) {
  1222. X        case 'I':
  1223. X        ival = -ival;
  1224. X        break;
  1225. X        case 'F':
  1226. X        fval = -fval;
  1227. X        break;
  1228. X        }
  1229. X        break;
  1230. X    case '/':
  1231. X        switch (mode) {
  1232. X        case 'I':
  1233. X        checkizero(ival);
  1234. X        ival = 1 / ival;
  1235. X        break;
  1236. X        case 'F':
  1237. X        checkfzero(fval);
  1238. X        fval = 1.0 / fval;
  1239. X        break;
  1240. X        }
  1241. X    }
  1242. X    }
  1243. X
  1244. X    /* handle each remaining argument */
  1245. X    while (moreargs()) {
  1246. X
  1247. X    /* get the next argument */
  1248. X    arg = xlgetarg();
  1249. X
  1250. X    /* check its type */
  1251. X    if (fixp(arg)) {
  1252. X        switch (mode) {
  1253. X        case 'I':
  1254. X            iarg = getfixnum(arg);
  1255. X            break;
  1256. X        case 'F':
  1257. X            farg = (FLOTYPE)getfixnum(arg);
  1258. X        break;
  1259. X        }
  1260. X    }
  1261. X    else if (floatp(arg)) {
  1262. X        switch (mode) {
  1263. X        case 'I':
  1264. X            fval = (FLOTYPE)ival;
  1265. X        farg = getflonum(arg);
  1266. X        mode = 'F';
  1267. X        break;
  1268. X        case 'F':
  1269. X            farg = getflonum(arg);
  1270. X        break;
  1271. X        }
  1272. X    }
  1273. X    else
  1274. X        xlerror("bad argument type",arg);
  1275. X
  1276. X    /* accumulate the result value */
  1277. X    switch (mode) {
  1278. X    case 'I':
  1279. X        switch (fcn) {
  1280. X        case '+':    ival += iarg; break;
  1281. X        case '-':    ival -= iarg; break;
  1282. X        case '*':    ival *= iarg; break;
  1283. X        case '/':    checkizero(iarg); ival /= iarg; break;
  1284. X        case '%':    checkizero(iarg); ival %= iarg; break;
  1285. X        case 'M':    if (iarg > ival) ival = iarg; break;
  1286. X        case 'm':    if (iarg < ival) ival = iarg; break;
  1287. X        case '&':    ival &= iarg; break;
  1288. X        case '|':    ival |= iarg; break;
  1289. X        case '^':    ival ^= iarg; break;
  1290. X        default:    badiop();
  1291. X        }
  1292. X        break;
  1293. X    case 'F':
  1294. X        switch (fcn) {
  1295. X        case '+':    fval += farg; break;
  1296. X        case '-':    fval -= farg; break;
  1297. X        case '*':    fval *= farg; break;
  1298. X        case '/':    checkfzero(farg); fval /= farg; break;
  1299. X        case 'M':    if (farg > fval) fval = farg; break;
  1300. X        case 'm':    if (farg < fval) fval = farg; break;
  1301. X        case 'E':    fval = pow(fval,farg); break;
  1302. X        default:    badfop();
  1303. X        }
  1304. X            break;
  1305. X    }
  1306. X    }
  1307. X
  1308. X    /* return the result */
  1309. X    switch (mode) {
  1310. X    case 'I':    return (cvfixnum(ival));
  1311. X    case 'F':    return (cvflonum(fval));
  1312. X    }
  1313. X}
  1314. X
  1315. X/* checkizero - check for integer division by zero */
  1316. Xcheckizero(iarg)
  1317. X  FIXTYPE iarg;
  1318. X{
  1319. X    if (iarg == 0)
  1320. X    xlfail("division by zero");
  1321. X}
  1322. X
  1323. X/* checkfzero - check for floating point division by zero */
  1324. Xcheckfzero(farg)
  1325. X  FLOTYPE farg;
  1326. X{
  1327. X    if (farg == 0.0)
  1328. X    xlfail("division by zero");
  1329. X}
  1330. X
  1331. X/* checkfneg - check for square root of a negative number */
  1332. Xcheckfneg(farg)
  1333. X  FLOTYPE farg;
  1334. X{
  1335. X    if (farg < 0.0)
  1336. X    xlfail("square root of a negative number");
  1337. X}
  1338. X
  1339. X/* unary functions */
  1340. XLVAL xlognot() { return (unary('~')); } /* lognot */
  1341. XLVAL xabs()    { return (unary('A')); } /* abs */
  1342. XLVAL xadd1()   { return (unary('+')); } /* 1+ */
  1343. XLVAL xsub1()   { return (unary('-')); } /* 1- */
  1344. XLVAL xsin()    { return (unary('S')); } /* sin */
  1345. XLVAL xcos()    { return (unary('C')); } /* cos */
  1346. XLVAL xtan()    { return (unary('T')); } /* tan */
  1347. XLVAL xasin()   { return (unary('s')); } /* asin */
  1348. XLVAL xacos()   { return (unary('c')); } /* acos */
  1349. XLVAL xatan()   { return (unary('t')); } /* atan */
  1350. XLVAL xexp()    { return (unary('E')); } /* exp */
  1351. XLVAL xsqrt()   { return (unary('R')); } /* sqrt */
  1352. XLVAL xfix()    { return (unary('I')); } /* truncate */
  1353. XLVAL xfloat()  { return (unary('F')); } /* float */
  1354. XLVAL xrand()   { return (unary('?')); } /* random */
  1355. X
  1356. X/* unary - handle unary operations */
  1357. XLOCAL LVAL unary(fcn)
  1358. X  int fcn;
  1359. X{
  1360. X    FLOTYPE fval;
  1361. X    FIXTYPE ival;
  1362. X    LVAL arg;
  1363. X
  1364. X    /* get the argument */
  1365. X    arg = xlgetarg();
  1366. X    xllastarg();
  1367. X
  1368. X    /* check its type */
  1369. X    if (fixp(arg)) {
  1370. X    ival = getfixnum(arg);
  1371. X    switch (fcn) {
  1372. X    case '~':    ival = ~ival; break;
  1373. X    case 'A':    ival = (ival < 0 ? -ival : ival); break;
  1374. X    case '+':    ival++; break;
  1375. X    case '-':    ival--; break;
  1376. X    case 'I':    break;
  1377. X    case 'F':    return (cvflonum((FLOTYPE)ival));
  1378. X    case '?':    ival = (FIXTYPE)osrand((int)ival); break;
  1379. X    default:    badiop();
  1380. X    }
  1381. X    return (cvfixnum(ival));
  1382. X    }
  1383. X    else if (floatp(arg)) {
  1384. X    fval = getflonum(arg);
  1385. X    switch (fcn) {
  1386. X    case 'A':    fval = (fval < 0.0 ? -fval : fval); break;
  1387. X    case '+':    fval += 1.0; break;
  1388. X    case '-':    fval -= 1.0; break;
  1389. X    case 'S':    fval = sin(fval); break;
  1390. X    case 'C':    fval = cos(fval); break;
  1391. X    case 'T':    fval = tan(fval); break;
  1392. X    case 's':    fval = asin(fval); break;
  1393. X    case 'c':    fval = acos(fval); break;
  1394. X    case 't':    fval = atan(fval); break;
  1395. X    case 'E':    fval = exp(fval); break;
  1396. X    case 'R':    checkfneg(fval); fval = sqrt(fval); break;
  1397. X    case 'I':    return (cvfixnum((FIXTYPE)fval));
  1398. X    case 'F':    break;
  1399. X    default:    badfop();
  1400. X    }
  1401. X    return (cvflonum(fval));
  1402. X    }
  1403. X    else
  1404. X    xlerror("bad argument type",arg);
  1405. X}
  1406. X
  1407. X/* unary predicates */
  1408. XLVAL xminusp() { return (predicate('-')); } /* minusp */
  1409. XLVAL xzerop()  { return (predicate('Z')); } /* zerop */
  1410. XLVAL xplusp()  { return (predicate('+')); } /* plusp */
  1411. XLVAL xevenp()  { return (predicate('E')); } /* evenp */
  1412. XLVAL xoddp()   { return (predicate('O')); } /* oddp */
  1413. X
  1414. X/* predicate - handle a predicate function */
  1415. XLOCAL LVAL predicate(fcn)
  1416. X  int fcn;
  1417. X{
  1418. X    FLOTYPE fval;
  1419. X    FIXTYPE ival;
  1420. X    LVAL arg;
  1421. X
  1422. X    /* get the argument */
  1423. X    arg = xlgetarg();
  1424. X    xllastarg();
  1425. X
  1426. X    /* check the argument type */
  1427. X    if (fixp(arg)) {
  1428. X    ival = getfixnum(arg);
  1429. X    switch (fcn) {
  1430. X    case '-':    ival = (ival < 0); break;
  1431. X    case 'Z':    ival = (ival == 0); break;
  1432. X    case '+':    ival = (ival > 0); break;
  1433. X    case 'E':    ival = ((ival & 1) == 0); break;
  1434. X    case 'O':    ival = ((ival & 1) != 0); break;
  1435. X    default:    badiop();
  1436. X    }
  1437. X    }
  1438. X    else if (floatp(arg)) {
  1439. X    fval = getflonum(arg);
  1440. X    switch (fcn) {
  1441. X    case '-':    ival = (fval < 0); break;
  1442. X    case 'Z':    ival = (fval == 0); break;
  1443. X    case '+':    ival = (fval > 0); break;
  1444. X    default:    badfop();
  1445. X    }
  1446. X    }
  1447. X    else
  1448. X    xlerror("bad argument type",arg);
  1449. X
  1450. X    /* return the result value */
  1451. X    return (ival ? true : NIL);
  1452. X}
  1453. X
  1454. X/* comparison functions */
  1455. XLVAL xlss() { return (compare('<')); } /* < */
  1456. XLVAL xleq() { return (compare('L')); } /* <= */
  1457. XLVAL xequ() { return (compare('=')); } /* = */
  1458. XLVAL xneq() { return (compare('#')); } /* /= */
  1459. XLVAL xgeq() { return (compare('G')); } /* >= */
  1460. XLVAL xgtr() { return (compare('>')); } /* > */
  1461. X
  1462. X/* compare - common compare function */
  1463. XLOCAL LVAL compare(fcn)
  1464. X  int fcn;
  1465. X{
  1466. X    FIXTYPE icmp,ival,iarg;
  1467. X    FLOTYPE fcmp,fval,farg;
  1468. X    LVAL arg;
  1469. X    int mode;
  1470. X
  1471. X    /* get the first argument */
  1472. X    arg = xlgetarg();
  1473. X
  1474. X    /* set the type of the first argument */
  1475. X    if (fixp(arg)) {
  1476. X    ival = getfixnum(arg);
  1477. X    mode = 'I';
  1478. X    }
  1479. X    else if (floatp(arg)) {
  1480. X    fval = getflonum(arg);
  1481. X    mode = 'F';
  1482. X    }
  1483. X    else
  1484. X    xlerror("bad argument type",arg);
  1485. X
  1486. X    /* handle each remaining argument */
  1487. X    for (icmp = TRUE; icmp && moreargs(); ival = iarg, fval = farg) {
  1488. X
  1489. X    /* get the next argument */
  1490. X    arg = xlgetarg();
  1491. X
  1492. X    /* check its type */
  1493. X    if (fixp(arg)) {
  1494. X        switch (mode) {
  1495. X        case 'I':
  1496. X            iarg = getfixnum(arg);
  1497. X            break;
  1498. X        case 'F':
  1499. X            farg = (FLOTYPE)getfixnum(arg);
  1500. X        break;
  1501. X        }
  1502. X    }
  1503. X    else if (floatp(arg)) {
  1504. X        switch (mode) {
  1505. X        case 'I':
  1506. X            fval = (FLOTYPE)ival;
  1507. X        farg = getflonum(arg);
  1508. X        mode = 'F';
  1509. X        break;
  1510. X        case 'F':
  1511. X            farg = getflonum(arg);
  1512. X        break;
  1513. X        }
  1514. X    }
  1515. X    else
  1516. X        xlerror("bad argument type",arg);
  1517. X
  1518. X    /* compute result of the compare */
  1519. X    switch (mode) {
  1520. X    case 'I':
  1521. X        icmp = ival - iarg;
  1522. X        switch (fcn) {
  1523. X        case '<':    icmp = (icmp < 0); break;
  1524. X        case 'L':    icmp = (icmp <= 0); break;
  1525. X        case '=':    icmp = (icmp == 0); break;
  1526. X        case '#':    icmp = (icmp != 0); break;
  1527. X        case 'G':    icmp = (icmp >= 0); break;
  1528. X        case '>':    icmp = (icmp > 0); break;
  1529. X        }
  1530. X        break;
  1531. X    case 'F':
  1532. X        fcmp = fval - farg;
  1533. X        switch (fcn) {
  1534. X        case '<':    icmp = (fcmp < 0.0); break;
  1535. X        case 'L':    icmp = (fcmp <= 0.0); break;
  1536. X        case '=':    icmp = (fcmp == 0.0); break;
  1537. X        case '#':    icmp = (fcmp != 0.0); break;
  1538. X        case 'G':    icmp = (fcmp >= 0.0); break;
  1539. X        case '>':    icmp = (fcmp > 0.0); break;
  1540. X        }
  1541. X        break;
  1542. X    }
  1543. X    }
  1544. X
  1545. X    /* return the result */
  1546. X    return (icmp ? true : NIL);
  1547. X}
  1548. X
  1549. X/* badiop - bad integer operation */
  1550. XLOCAL badiop()
  1551. X{
  1552. X    xlfail("bad integer operation");
  1553. X}
  1554. X
  1555. X/* badfop - bad floating point operation */
  1556. XLOCAL badfop()
  1557. X{
  1558. X    xlfail("bad floating point operation");
  1559. X}
  1560. SHAR_EOF
  1561. if test 9993 -ne "`wc -c 'xlmath.c'`"
  1562. then
  1563.     echo shar: error transmitting "'xlmath.c'" '(should have been 9993 characters)'
  1564. fi
  1565. echo shar: extracting "'xlobj.c'" '(11545 characters)'
  1566. if test -f 'xlobj.c'
  1567. then
  1568.     echo shar: over-writing existing file "'xlobj.c'"
  1569. fi
  1570. sed 's/^X//' << \SHAR_EOF > 'xlobj.c'
  1571. X/* xlobj - xlisp object functions */
  1572. X/*    Copyright (c) 1985, by David Michael Betz
  1573. X    All Rights Reserved
  1574. X    Permission is granted for unrestricted non-commercial use    */
  1575. X
  1576. X#include "xlisp.h"
  1577. X
  1578. X/* external variables */
  1579. Xextern LVAL xlenv,xlfenv,xlvalue;
  1580. Xextern LVAL s_stdout,s_lambda;
  1581. X
  1582. X/* local variables */
  1583. Xstatic LVAL s_self,k_new,k_isnew;
  1584. Xstatic LVAL class,object;
  1585. X
  1586. X/* instance variable numbers for the class 'Class' */
  1587. X#define MESSAGES    0    /* list of messages */
  1588. X#define IVARS        1    /* list of instance variable names */
  1589. X#define CVARS        2    /* list of class variable names */
  1590. X#define CVALS        3    /* list of class variable values */
  1591. X#define SUPERCLASS    4    /* pointer to the superclass */
  1592. X#define IVARCNT        5    /* number of class instance variables */
  1593. X#define IVARTOTAL    6    /* total number of instance variables */
  1594. X
  1595. X/* number of instance variables for the class 'Class' */
  1596. X#define CLASSSIZE    7
  1597. X
  1598. X/* forward declarations */
  1599. XFORWARD LVAL entermsg();
  1600. XFORWARD LVAL sendmsg();
  1601. XFORWARD LVAL evmethod();
  1602. X
  1603. X/* xsend - send a message to an object */
  1604. XLVAL xsend()
  1605. X{
  1606. X    LVAL obj;
  1607. X    obj = xlgaobject();
  1608. X    return (sendmsg(obj,getclass(obj),xlgasymbol()));
  1609. X}
  1610. X
  1611. X/* xsendsuper - send a message to the superclass of an object */
  1612. XLVAL xsendsuper()
  1613. X{
  1614. X    LVAL env,p;
  1615. X    for (env = xlenv; env; env = cdr(env))
  1616. X    if ((p = car(env)) && objectp(car(p)))
  1617. X        return (sendmsg(car(p),
  1618. X                getivar(cdr(p),SUPERCLASS),
  1619. X                xlgasymbol()));
  1620. X    xlfail("not in a method");
  1621. X}
  1622. X
  1623. X/* xlclass - define a class */
  1624. XLVAL xlclass(name,vcnt)
  1625. X  char *name; int vcnt;
  1626. X{
  1627. X    LVAL sym,cls;
  1628. X
  1629. X    /* create the class */
  1630. X    sym = xlenter(name);
  1631. X    cls = newobject(class,CLASSSIZE);
  1632. X    setvalue(sym,cls);
  1633. X
  1634. X    /* set the instance variable counts */
  1635. X    setivar(cls,IVARCNT,cvfixnum((FIXTYPE)vcnt));
  1636. X    setivar(cls,IVARTOTAL,cvfixnum((FIXTYPE)vcnt));
  1637. X
  1638. X    /* set the superclass to 'Object' */
  1639. X    setivar(cls,SUPERCLASS,object);
  1640. X
  1641. X    /* return the new class */
  1642. X    return (cls);
  1643. X}
  1644. X
  1645. X/* xladdivar - enter an instance variable */
  1646. Xxladdivar(cls,var)
  1647. X  LVAL cls; char *var;
  1648. X{
  1649. X    setivar(cls,IVARS,cons(xlenter(var),getivar(cls,IVARS)));
  1650. X}
  1651. X
  1652. X/* xladdmsg - add a message to a class */
  1653. Xxladdmsg(cls,msg,offset)
  1654. X  LVAL cls; char *msg; int offset;
  1655. X{
  1656. X    extern FUNDEF funtab[];
  1657. X    LVAL mptr;
  1658. X
  1659. X    /* enter the message selector */
  1660. X    mptr = entermsg(cls,xlenter(msg));
  1661. X
  1662. X    /* store the method for this message */
  1663. X    rplacd(mptr,cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset));
  1664. X}
  1665. X
  1666. X/* xlobgetvalue - get the value of an instance variable */
  1667. Xint xlobgetvalue(pair,sym,pval)
  1668. X  LVAL pair,sym,*pval;
  1669. X{
  1670. X    LVAL cls,names;
  1671. X    int ivtotal,n;
  1672. X
  1673. X    /* find the instance or class variable */
  1674. X    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {
  1675. X
  1676. X    /* check the instance variables */
  1677. X    names = getivar(cls,IVARS);
  1678. X    ivtotal = getivcnt(cls,IVARTOTAL);
  1679. X    for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
  1680. X        if (car(names) == sym) {
  1681. X        *pval = getivar(car(pair),n);
  1682. X        return (TRUE);
  1683. X        }
  1684. X        names = cdr(names);
  1685. X    }
  1686. X
  1687. X    /* check the class variables */
  1688. X    names = getivar(cls,CVARS);
  1689. X    for (n = 0; consp(names); ++n) {
  1690. X        if (car(names) == sym) {
  1691. X        *pval = getelement(getivar(cls,CVALS),n);
  1692. X        return (TRUE);
  1693. X        }
  1694. X        names = cdr(names);
  1695. X    }
  1696. X    }
  1697. X
  1698. X    /* variable not found */
  1699. X    return (FALSE);
  1700. X}
  1701. X
  1702. X/* xlobsetvalue - set the value of an instance variable */
  1703. Xint xlobsetvalue(pair,sym,val)
  1704. X  LVAL pair,sym,val;
  1705. X{
  1706. X    LVAL cls,names;
  1707. X    int ivtotal,n;
  1708. X
  1709. X    /* find the instance or class variable */
  1710. X    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {
  1711. X
  1712. X    /* check the instance variables */
  1713. X    names = getivar(cls,IVARS);
  1714. X    ivtotal = getivcnt(cls,IVARTOTAL);
  1715. X    for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
  1716. X        if (car(names) == sym) {
  1717. X        setivar(car(pair),n,val);
  1718. X        return (TRUE);
  1719. X        }
  1720. X        names = cdr(names);
  1721. X    }
  1722. X
  1723. X    /* check the class variables */
  1724. X    names = getivar(cls,CVARS);
  1725. X    for (n = 0; consp(names); ++n) {
  1726. X        if (car(names) == sym) {
  1727. X        setelement(getivar(cls,CVALS),n,val);
  1728. X        return (TRUE);
  1729. X        }
  1730. X        names = cdr(names);
  1731. X    }
  1732. X    }
  1733. X
  1734. X    /* variable not found */
  1735. X    return (FALSE);
  1736. X}
  1737. X
  1738. X/* obisnew - default 'isnew' method */
  1739. XLVAL obisnew()
  1740. X{
  1741. X    LVAL self;
  1742. X    self = xlgaobject();
  1743. X    xllastarg();
  1744. X    return (self);
  1745. X}
  1746. X
  1747. X/* obclass - get the class of an object */
  1748. XLVAL obclass()
  1749. X{
  1750. X    LVAL self;
  1751. X    self = xlgaobject();
  1752. X    xllastarg();
  1753. X    return (getclass(self));
  1754. X}
  1755. X
  1756. X/* obshow - show the instance variables of an object */
  1757. XLVAL obshow()
  1758. X{
  1759. X    LVAL self,fptr,cls,names;
  1760. X    int ivtotal,n;
  1761. X
  1762. X    /* get self and the file pointer */
  1763. X    self = xlgaobject();
  1764. X    fptr = (moreargs() ? xlgetfile() : getvalue(s_stdout));
  1765. X    xllastarg();
  1766. X
  1767. X    /* get the object's class */
  1768. X    cls = getclass(self);
  1769. X
  1770. X    /* print the object and class */
  1771. X    xlputstr(fptr,"Object is ");
  1772. X    xlprint(fptr,self,TRUE);
  1773. X    xlputstr(fptr,", Class is ");
  1774. X    xlprint(fptr,cls,TRUE);
  1775. X    xlterpri(fptr);
  1776. X
  1777. X    /* print the object's instance variables */
  1778. X    for (; cls; cls = getivar(cls,SUPERCLASS)) {
  1779. X    names = getivar(cls,IVARS);
  1780. X    ivtotal = getivcnt(cls,IVARTOTAL);
  1781. X    for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {
  1782. X        xlputstr(fptr,"  ");
  1783. X        xlprint(fptr,car(names),TRUE);
  1784. X        xlputstr(fptr," = ");
  1785. X        xlprint(fptr,getivar(self,n),TRUE);
  1786. X        xlterpri(fptr);
  1787. X        names = cdr(names);
  1788. X    }
  1789. X    }
  1790. X
  1791. X    /* return the object */
  1792. X    return (self);
  1793. X}
  1794. X
  1795. X/* clnew - create a new object instance */
  1796. XLVAL clnew()
  1797. X{
  1798. X    LVAL self;
  1799. X    self = xlgaobject();
  1800. X    return (newobject(self,getivcnt(self,IVARTOTAL)));
  1801. X}
  1802. X
  1803. X/* clisnew - initialize a new class */
  1804. XLVAL clisnew()
  1805. X{
  1806. X    LVAL self,ivars,cvars,super;
  1807. X    int n;
  1808. X
  1809. X    /* get self, the ivars, cvars and superclass */
  1810. X    self = xlgaobject();
  1811. X    ivars = xlgalist();
  1812. X    cvars = (moreargs() ? xlgalist() : NIL);
  1813. X    super = (moreargs() ? xlgaobject() : object);
  1814. X    xllastarg();
  1815. X
  1816. X    /* store the instance and class variable lists and the superclass */
  1817. X    setivar(self,IVARS,ivars);
  1818. X    setivar(self,CVARS,cvars);
  1819. X    setivar(self,CVALS,(cvars ? newvector(listlength(cvars)) : NIL));
  1820. X    setivar(self,SUPERCLASS,super);
  1821. X
  1822. X    /* compute the instance variable count */
  1823. X    n = listlength(ivars);
  1824. X    setivar(self,IVARCNT,cvfixnum((FIXTYPE)n));
  1825. X    n += getivcnt(super,IVARTOTAL);
  1826. X    setivar(self,IVARTOTAL,cvfixnum((FIXTYPE)n));
  1827. X
  1828. X    /* return the new class object */
  1829. X    return (self);
  1830. X}
  1831. X
  1832. X/* clanswer - define a method for answering a message */
  1833. XLVAL clanswer()
  1834. X{
  1835. X    LVAL self,msg,fargs,code,mptr;
  1836. X
  1837. X    /* message symbol, formal argument list and code */
  1838. X    self = xlgaobject();
  1839. X    msg = xlgasymbol();
  1840. X    fargs = xlgalist();
  1841. X    code = xlgalist();
  1842. X    xllastarg();
  1843. X
  1844. X    /* make a new message list entry */
  1845. X    mptr = entermsg(self,msg);
  1846. X
  1847. X    /* setup the message node */
  1848. X    xlprot1(fargs);
  1849. X    fargs = cons(s_self,fargs); /* add 'self' as the first argument */
  1850. X    rplacd(mptr,xlclose(msg,s_lambda,fargs,code,NIL,NIL));
  1851. X    xlpop();
  1852. X
  1853. X    /* return the object */
  1854. X    return (self);
  1855. X}
  1856. X
  1857. X/* entermsg - add a message to a class */
  1858. XLOCAL LVAL entermsg(cls,msg)
  1859. X  LVAL cls,msg;
  1860. X{
  1861. X    LVAL lptr,mptr;
  1862. X
  1863. X    /* lookup the message */
  1864. X    for (lptr = getivar(cls,MESSAGES); lptr; lptr = cdr(lptr))
  1865. X    if (car(mptr = car(lptr)) == msg)
  1866. X        return (mptr);
  1867. X
  1868. X    /* allocate a new message entry if one wasn't found */
  1869. X    xlsave1(mptr);
  1870. X    mptr = consa(msg);
  1871. X    setivar(cls,MESSAGES,cons(mptr,getivar(cls,MESSAGES)));
  1872. X    xlpop();
  1873. X
  1874. X    /* return the symbol node */
  1875. X    return (mptr);
  1876. X}
  1877. X
  1878. X/* sendmsg - send a message to an object */
  1879. XLOCAL LVAL sendmsg(obj,cls,sym)
  1880. X  LVAL obj,cls,sym;
  1881. X{
  1882. X    LVAL msg,msgcls,method,val,p;
  1883. X
  1884. X    /* look for the message in the class or superclasses */
  1885. X    for (msgcls = cls; msgcls; ) {
  1886. X
  1887. X    /* lookup the message in this class */
  1888. X    for (p = getivar(msgcls,MESSAGES); p; p = cdr(p))
  1889. X        if ((msg = car(p)) && car(msg) == sym)
  1890. X        goto send_message;
  1891. X
  1892. X    /* look in class's superclass */
  1893. X    msgcls = getivar(msgcls,SUPERCLASS);
  1894. X    }
  1895. X
  1896. X    /* message not found */
  1897. X    xlerror("no method for this message",sym);
  1898. X
  1899. Xsend_message:
  1900. X
  1901. X    /* insert the value for 'self' (overwrites message selector) */
  1902. X    *--xlargv = obj;
  1903. X    ++xlargc;
  1904. X    
  1905. X    /* invoke the method */
  1906. X    if ((method = cdr(msg)) == NULL)
  1907. X    xlerror("bad method",method);
  1908. X    switch (ntype(method)) {
  1909. X    case SUBR:
  1910. X    val = (*getsubr(method))();
  1911. X    break;
  1912. X    case CLOSURE:
  1913. X    if (gettype(method) != s_lambda)
  1914. X        xlerror("bad method",method);
  1915. X    val = evmethod(obj,msgcls,method);
  1916. X    break;
  1917. X    default:
  1918. X    xlerror("bad method",method);
  1919. X    }
  1920. X
  1921. X    /* after creating an object, send it the ":isnew" message */
  1922. X    if (car(msg) == k_new && val) {
  1923. X    xlprot1(val);
  1924. X    sendmsg(val,getclass(val),k_isnew);
  1925. X    xlpop();
  1926. X    }
  1927. X    
  1928. X    /* return the result value */
  1929. X    return (val);
  1930. X}
  1931. X
  1932. X/* evmethod - evaluate a method */
  1933. XLOCAL LVAL evmethod(obj,msgcls,method)
  1934. X  LVAL obj,msgcls,method;
  1935. X{
  1936. X    LVAL oldenv,oldfenv,cptr,name,val;
  1937. X    CONTEXT cntxt;
  1938. X
  1939. X    /* protect some pointers */
  1940. X    xlstkcheck(3);
  1941. X    xlsave(oldenv);
  1942. X    xlsave(oldfenv);
  1943. X    xlsave(cptr);
  1944. X
  1945. X    /* create an 'object' stack entry and a new environment frame */
  1946. X    oldenv = xlenv;
  1947. X    oldfenv = xlfenv;
  1948. X    xlenv = cons(cons(obj,msgcls),getenv(method));
  1949. X    xlenv = xlframe(xlenv);
  1950. X    xlfenv = getfenv(method);
  1951. X
  1952. X    /* bind the formal parameters */
  1953. X    xlabind(method,xlargc,xlargv);
  1954. X
  1955. X    /* setup the implicit block */
  1956. X    if (name = getname(method))
  1957. X    xlbegin(&cntxt,CF_RETURN,name);
  1958. X
  1959. X    /* execute the block */
  1960. X    if (name && setjmp(cntxt.c_jmpbuf))
  1961. X    val = xlvalue;
  1962. X    else
  1963. X    for (cptr = getbody(method); consp(cptr); cptr = cdr(cptr))
  1964. X        val = xleval(car(cptr));
  1965. X
  1966. X    /* finish the block context */
  1967. X    if (name)
  1968. X    xlend(&cntxt);
  1969. X
  1970. X    /* restore the environment */
  1971. X    xlenv = oldenv;
  1972. X    xlfenv = oldfenv;
  1973. X
  1974. X    /* restore the stack */
  1975. X    xlpopn(3);
  1976. X
  1977. X    /* return the result value */
  1978. X    return (val);
  1979. X}
  1980. X
  1981. X/* getivcnt - get the number of instance variables for a class */
  1982. XLOCAL int getivcnt(cls,ivar)
  1983. X  LVAL cls; int ivar;
  1984. X{
  1985. X    LVAL cnt;
  1986. X    if ((cnt = getivar(cls,ivar)) == NIL || !fixp(cnt))
  1987. X    xlfail("bad value for instance variable count");
  1988. X    return ((int)getfixnum(cnt));
  1989. X}
  1990. X
  1991. X/* listlength - find the length of a list */
  1992. XLOCAL int listlength(list)
  1993. X  LVAL list;
  1994. X{
  1995. X    int len;
  1996. X    for (len = 0; consp(list); len++)
  1997. X    list = cdr(list);
  1998. X    return (len);
  1999. X}
  2000. X
  2001. X/* obsymbols - initialize symbols */
  2002. Xobsymbols()
  2003. X{
  2004. X    /* enter the object related symbols */
  2005. X    s_self  = xlenter("SELF");
  2006. X    k_new   = xlenter(":NEW");
  2007. X    k_isnew = xlenter(":ISNEW");
  2008. X
  2009. X    /* get the Object and Class symbol values */
  2010. X    object = getvalue(xlenter("OBJECT"));
  2011. X    class  = getvalue(xlenter("CLASS"));
  2012. X}
  2013. X
  2014. X/* xloinit - object function initialization routine */
  2015. Xxloinit()
  2016. X{
  2017. X    /* create the 'Class' object */
  2018. X    class = xlclass("CLASS",CLASSSIZE);
  2019. X    setelement(class,0,class);
  2020. X
  2021. X    /* create the 'Object' object */
  2022. X    object = xlclass("OBJECT",0);
  2023. X
  2024. X    /* finish initializing 'class' */
  2025. X    setivar(class,SUPERCLASS,object);
  2026. X    xladdivar(class,"IVARTOTAL");    /* ivar number 6 */
  2027. X    xladdivar(class,"IVARCNT");        /* ivar number 5 */
  2028. X    xladdivar(class,"SUPERCLASS");    /* ivar number 4 */
  2029. X    xladdivar(class,"CVALS");        /* ivar number 3 */
  2030. X    xladdivar(class,"CVARS");        /* ivar number 2 */
  2031. X    xladdivar(class,"IVARS");        /* ivar number 1 */
  2032. X    xladdivar(class,"MESSAGES");    /* ivar number 0 */
  2033. X    xladdmsg(class,":NEW",FT_CLNEW);
  2034. X    xladdmsg(class,":ISNEW",FT_CLISNEW);
  2035. X    xladdmsg(class,":ANSWER",FT_CLANSWER);
  2036. X
  2037. X    /* finish initializing 'object' */
  2038. X    setivar(object,SUPERCLASS,NIL);
  2039. X    xladdmsg(object,":ISNEW",FT_OBISNEW);
  2040. X    xladdmsg(object,":CLASS",FT_OBCLASS);
  2041. X    xladdmsg(object,":SHOW",FT_OBSHOW);
  2042. X}
  2043. X
  2044. SHAR_EOF
  2045. if test 11545 -ne "`wc -c 'xlobj.c'`"
  2046. then
  2047.     echo shar: error transmitting "'xlobj.c'" '(should have been 11545 characters)'
  2048. fi
  2049. echo shar: extracting "'xlpp.c'" '(2111 characters)'
  2050. if test -f 'xlpp.c'
  2051. then
  2052.     echo shar: over-writing existing file "'xlpp.c'"
  2053. fi
  2054. sed 's/^X//' << \SHAR_EOF > 'xlpp.c'
  2055. X/* xlpp.c - xlisp pretty printer */
  2056. X/*    Copyright (c) 1985, by David Betz
  2057. X    All Rights Reserved            */
  2058. X
  2059. X#include "xlisp.h"
  2060. X
  2061. X/* external variables */
  2062. Xextern LVAL s_stdout;
  2063. Xextern int xlfsize;
  2064. X
  2065. X/* local variables */
  2066. Xstatic int pplevel,ppmargin,ppmaxlen;
  2067. Xstatic LVAL ppfile;
  2068. X
  2069. X/* xpp - pretty-print an expression */
  2070. XLVAL xpp()
  2071. X{
  2072. X    LVAL expr;
  2073. X
  2074. X    /* get expression to print and file pointer */
  2075. X    expr = xlgetarg();
  2076. X    ppfile = (moreargs() ? xlgetfile() : getvalue(s_stdout));
  2077. X    xllastarg();
  2078. X
  2079. X    /* pretty print the expression */
  2080. X    pplevel = ppmargin = 0; ppmaxlen = 40;
  2081. X    pp(expr); ppterpri(ppfile);
  2082. X
  2083. X    /* return nil */
  2084. X    return (NIL);
  2085. X}
  2086. X
  2087. X/* pp - pretty print an expression */
  2088. XLOCAL pp(expr)
  2089. X  LVAL expr;
  2090. X{
  2091. X    if (consp(expr))
  2092. X    pplist(expr);
  2093. X    else
  2094. X    ppexpr(expr);
  2095. X}
  2096. X
  2097. X/* pplist - pretty print a list */
  2098. XLOCAL pplist(expr)
  2099. X  LVAL expr;
  2100. X{
  2101. X    int n;
  2102. X
  2103. X    /* if the expression will fit on one line, print it on one */
  2104. X    if ((n = flatsize(expr)) < ppmaxlen) {
  2105. X    xlprint(ppfile,expr,TRUE);
  2106. X    pplevel += n;
  2107. X    }
  2108. X
  2109. X    /* otherwise print it on several lines */
  2110. X    else {
  2111. X    n = ppmargin;
  2112. X    ppputc('(');
  2113. X    if (atom(car(expr))) {
  2114. X        ppexpr(car(expr));
  2115. X        ppputc(' ');
  2116. X        ppmargin = pplevel;
  2117. X        expr = cdr(expr);
  2118. X    }
  2119. X    else
  2120. X        ppmargin = pplevel;
  2121. X    for (; consp(expr); expr = cdr(expr)) {
  2122. X        pp(car(expr));
  2123. X        if (consp(cdr(expr)))
  2124. X        ppterpri();
  2125. X    }
  2126. X    if (expr != NIL) {
  2127. X        ppputc(' '); ppputc('.'); ppputc(' ');
  2128. X        ppexpr(expr);
  2129. X    }
  2130. X    ppputc(')');
  2131. X    ppmargin = n;
  2132. X    }
  2133. X}
  2134. X
  2135. X/* ppexpr - print an expression and update the indent level */
  2136. XLOCAL ppexpr(expr)
  2137. X  LVAL expr;
  2138. X{
  2139. X    xlprint(ppfile,expr,TRUE);
  2140. X    pplevel += flatsize(expr);
  2141. X}
  2142. X
  2143. X/* ppputc - output a character and update the indent level */
  2144. XLOCAL ppputc(ch)
  2145. X  int ch;
  2146. X{
  2147. X    xlputc(ppfile,ch);
  2148. X    pplevel++;
  2149. X}
  2150. X
  2151. X/* ppterpri - terminate the print line and indent */
  2152. XLOCAL ppterpri()
  2153. X{
  2154. X    xlterpri(ppfile);
  2155. X    for (pplevel = 0; pplevel < ppmargin; pplevel++)
  2156. X    xlputc(ppfile,' ');
  2157. X}
  2158. X
  2159. X/* flatsize - compute the flat size of an expression */
  2160. XLOCAL int flatsize(expr)
  2161. X  LVAL expr;
  2162. X{
  2163. X    xlfsize = 0;
  2164. X    xlprint(NIL,expr,TRUE);
  2165. X    return (xlfsize);
  2166. X}
  2167. SHAR_EOF
  2168. if test 2111 -ne "`wc -c 'xlpp.c'`"
  2169. then
  2170.     echo shar: error transmitting "'xlpp.c'" '(should have been 2111 characters)'
  2171. fi
  2172. echo shar: extracting "'xlprin.c'" '(7244 characters)'
  2173. if test -f 'xlprin.c'
  2174. then
  2175.     echo shar: over-writing existing file "'xlprin.c'"
  2176. fi
  2177. sed 's/^X//' << \SHAR_EOF > 'xlprin.c'
  2178. X/* xlprint - xlisp print routine */
  2179. X/*    Copyright (c) 1985, by David Michael Betz
  2180. X    All Rights Reserved
  2181. X    Permission is granted for unrestricted non-commercial use    */
  2182. X
  2183. X#include "xlisp.h"
  2184. X
  2185. X/* external variables */
  2186. Xextern LVAL tentry();
  2187. Xextern LVAL s_printcase,k_downcase,k_const,k_nmacro;
  2188. Xextern LVAL s_ifmt,s_ffmt;
  2189. Xextern FUNDEF funtab[];
  2190. Xextern char buf[];
  2191. X
  2192. X/* xlprint - print an xlisp value */
  2193. Xxlprint(fptr,vptr,flag)
  2194. X  LVAL fptr,vptr; int flag;
  2195. X{
  2196. X    LVAL nptr,next;
  2197. X    int n,i;
  2198. X
  2199. X    /* print nil */
  2200. X    if (vptr == NIL) {
  2201. X    putsymbol(fptr,"NIL",flag);
  2202. X    return;
  2203. X    }
  2204. X
  2205. X    /* check value type */
  2206. X    switch (ntype(vptr)) {
  2207. X    case SUBR:
  2208. X        putsubr(fptr,"Subr",vptr);
  2209. X        break;
  2210. X    case FSUBR:
  2211. X        putsubr(fptr,"FSubr",vptr);
  2212. X        break;
  2213. X    case CONS:
  2214. X        xlputc(fptr,'(');
  2215. X        for (nptr = vptr; nptr != NIL; nptr = next) {
  2216. X            xlprint(fptr,car(nptr),flag);
  2217. X        if (next = cdr(nptr))
  2218. X            if (consp(next))
  2219. X            xlputc(fptr,' ');
  2220. X            else {
  2221. X            xlputstr(fptr," . ");
  2222. X            xlprint(fptr,next,flag);
  2223. X            break;
  2224. X            }
  2225. X        }
  2226. X        xlputc(fptr,')');
  2227. X        break;
  2228. X    case SYMBOL:
  2229. X        putsymbol(fptr,getstring(getpname(vptr)),flag);
  2230. X        break;
  2231. X    case FIXNUM:
  2232. X        putfixnum(fptr,getfixnum(vptr));
  2233. X        break;
  2234. X    case FLONUM:
  2235. X        putflonum(fptr,getflonum(vptr));
  2236. X        break;
  2237. X    case CHAR:
  2238. X        putchcode(fptr,getchcode(vptr),flag);
  2239. X        break;
  2240. X    case STRING:
  2241. X        if (flag)
  2242. X        putqstring(fptr,vptr);
  2243. X        else
  2244. X        putstring(fptr,vptr);
  2245. X        break;
  2246. X    case STREAM:
  2247. X        putatm(fptr,"File-Stream",vptr);
  2248. X        break;
  2249. X    case USTREAM:
  2250. X        putatm(fptr,"Unnamed-Stream",vptr);
  2251. X        break;
  2252. X    case OBJECT:
  2253. X        putatm(fptr,"Object",vptr);
  2254. X        break;
  2255. X    case VECTOR:
  2256. X        xlputc(fptr,'#'); xlputc(fptr,'(');
  2257. X        for (i = 0, n = getsize(vptr) - 1; i <= n; ++i) {
  2258. X        xlprint(fptr,getelement(vptr,i),flag);
  2259. X        if (i != n) xlputc(fptr,' ');
  2260. X        }
  2261. X        xlputc(fptr,')');
  2262. X        break;
  2263. X    case STRUCT:
  2264. X        xlprstruct(fptr,vptr,flag);
  2265. X        break;
  2266. X    case CLOSURE:
  2267. X        putclosure(fptr,vptr);
  2268. X        break;
  2269. X    case FREE:
  2270. X        putatm(fptr,"Free",vptr);
  2271. X        break;
  2272. X    default:
  2273. X        putatm(fptr,"Foo",vptr);
  2274. X        break;
  2275. X    }
  2276. X}
  2277. X
  2278. X/* xlterpri - terminate the current print line */
  2279. Xxlterpri(fptr)
  2280. X  LVAL fptr;
  2281. X{
  2282. X    xlputc(fptr,'\n');
  2283. X}
  2284. X
  2285. X/* xlputstr - output a string */
  2286. Xxlputstr(fptr,str)
  2287. X  LVAL fptr; char *str;
  2288. X{
  2289. X    while (*str)
  2290. X    xlputc(fptr,*str++);
  2291. X}
  2292. X
  2293. X/* putsymbol - output a symbol */
  2294. XLOCAL putsymbol(fptr,str,escflag)
  2295. X  LVAL fptr; char *str; int escflag;
  2296. X{
  2297. X    int downcase,ch;
  2298. X    LVAL type;
  2299. X    char *p;
  2300. X
  2301. X    /* check for printing without escapes */
  2302. X    if (!escflag) {
  2303. X    xlputstr(fptr,str);
  2304. X    return;
  2305. X    }
  2306. X
  2307. X    /* check to see if symbol needs escape characters */
  2308. X    if (tentry(*str) == k_const) {
  2309. X    for (p = str; *p; ++p)
  2310. X        if (islower(*p)
  2311. X        ||  ((type = tentry(*p)) != k_const
  2312. X          && (!consp(type) || car(type) != k_nmacro))) {
  2313. X        xlputc(fptr,'|');
  2314. X        while (*str) {
  2315. X            if (*str == '\\' || *str == '|')
  2316. X            xlputc(fptr,'\\');
  2317. X            xlputc(fptr,*str++);
  2318. X        }
  2319. X        xlputc(fptr,'|');
  2320. X        return;
  2321. X        }
  2322. X    }
  2323. X
  2324. X    /* get the case translation flag */
  2325. X    downcase = (getvalue(s_printcase) == k_downcase);
  2326. X
  2327. X    /* check for the first character being '#' */
  2328. X    if (*str == '#' || *str == '.' || isnumber(str,NULL))
  2329. X    xlputc(fptr,'\\');
  2330. X
  2331. X    /* output each character */
  2332. X    while ((ch = *str++) != '\0') {
  2333. X    /* don't escape colon until we add support for packages */
  2334. X    if (ch == '\\' || ch == '|' /* || ch == ':' */)
  2335. X        xlputc(fptr,'\\');
  2336. X    xlputc(fptr,(downcase && isupper(ch) ? tolower(ch) : ch));
  2337. X    }
  2338. X}
  2339. X
  2340. X/* putstring - output a string */
  2341. XLOCAL putstring(fptr,str)
  2342. X  LVAL fptr,str;
  2343. X{
  2344. X    unsigned char *p;
  2345. X    int ch;
  2346. X
  2347. X    /* output each character */
  2348. X    for (p = getstring(str); (ch = *p) != '\0'; ++p)
  2349. X    xlputc(fptr,ch);
  2350. X}
  2351. X
  2352. X/* putqstring - output a quoted string */
  2353. XLOCAL putqstring(fptr,str)
  2354. X  LVAL fptr,str;
  2355. X{
  2356. X    unsigned char *p;
  2357. X    int ch;
  2358. X
  2359. X    /* get the string pointer */
  2360. X    p = getstring(str);
  2361. X
  2362. X    /* output the initial quote */
  2363. X    xlputc(fptr,'"');
  2364. X
  2365. X    /* output each character in the string */
  2366. X    for (p = getstring(str); (ch = *p) != '\0'; ++p)
  2367. X
  2368. X    /* check for a control character */
  2369. X    if (ch < 040 || ch == '\\' || ch > 0176) {
  2370. X        xlputc(fptr,'\\');
  2371. X        switch (ch) {
  2372. X        case '\011':
  2373. X            xlputc(fptr,'t');
  2374. X            break;
  2375. X        case '\012':
  2376. X            xlputc(fptr,'n');
  2377. X            break;
  2378. X        case '\014':
  2379. X            xlputc(fptr,'f');
  2380. X            break;
  2381. X        case '\015':
  2382. X            xlputc(fptr,'r');
  2383. X            break;
  2384. X        case '\\':
  2385. X            xlputc(fptr,'\\');
  2386. X            break;
  2387. X        default:
  2388. X            putoct(fptr,ch);
  2389. X            break;
  2390. X        }
  2391. X    }
  2392. X
  2393. X    /* output a normal character */
  2394. X    else
  2395. X        xlputc(fptr,ch);
  2396. X
  2397. X    /* output the terminating quote */
  2398. X    xlputc(fptr,'"');
  2399. X}
  2400. X
  2401. X/* putatm - output an atom */
  2402. XLOCAL putatm(fptr,tag,val)
  2403. X  LVAL fptr; char *tag; LVAL val;
  2404. X{
  2405. X    sprintf(buf,"#<%s: #",tag); xlputstr(fptr,buf);
  2406. X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
  2407. X    xlputc(fptr,'>');
  2408. X}
  2409. X
  2410. X/* putsubr - output a subr/fsubr */
  2411. XLOCAL putsubr(fptr,tag,val)
  2412. X  LVAL fptr; char *tag; LVAL val;
  2413. X{
  2414. X    sprintf(buf,"#<%s-%s: #",tag,funtab[getoffset(val)].fd_name);
  2415. X    xlputstr(fptr,buf);
  2416. X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
  2417. X    xlputc(fptr,'>');
  2418. X}
  2419. X
  2420. X/* putclosure - output a closure */
  2421. XLOCAL putclosure(fptr,val)
  2422. X  LVAL fptr,val;
  2423. X{
  2424. X    LVAL name;
  2425. X    if (name = getname(val))
  2426. X    sprintf(buf,"#<Closure-%s: #",getstring(getpname(name)));
  2427. X    else
  2428. X    strcpy(buf,"#<Closure: #");
  2429. X    xlputstr(fptr,buf);
  2430. X    sprintf(buf,AFMT,val); xlputstr(fptr,buf);
  2431. X    xlputc(fptr,'>');
  2432. X/*
  2433. X    xlputstr(fptr,"\nName:   "); xlprint(fptr,getname(val),TRUE);
  2434. X    xlputstr(fptr,"\nType:   "); xlprint(fptr,gettype(val),TRUE);
  2435. X    xlputstr(fptr,"\nLambda: "); xlprint(fptr,getlambda(val),TRUE);
  2436. X    xlputstr(fptr,"\nArgs:   "); xlprint(fptr,getargs(val),TRUE);
  2437. X    xlputstr(fptr,"\nOargs:  "); xlprint(fptr,getoargs(val),TRUE);
  2438. X    xlputstr(fptr,"\nRest:   "); xlprint(fptr,getrest(val),TRUE);
  2439. X    xlputstr(fptr,"\nKargs:  "); xlprint(fptr,getkargs(val),TRUE);
  2440. X    xlputstr(fptr,"\nAargs:  "); xlprint(fptr,getaargs(val),TRUE);
  2441. X    xlputstr(fptr,"\nBody:   "); xlprint(fptr,getbody(val),TRUE);
  2442. X    xlputstr(fptr,"\nEnv:    "); xlprint(fptr,getenv(val),TRUE);
  2443. X    xlputstr(fptr,"\nFenv:   "); xlprint(fptr,getfenv(val),TRUE);
  2444. X*/
  2445. X}
  2446. X
  2447. X/* putfixnum - output a fixnum */
  2448. XLOCAL putfixnum(fptr,n)
  2449. X  LVAL fptr; FIXTYPE n;
  2450. X{
  2451. X    unsigned char *fmt;
  2452. X    LVAL val;
  2453. X    fmt = ((val = getvalue(s_ifmt)) && stringp(val) ? getstring(val)
  2454. X                            : (unsigned char *)IFMT);
  2455. X    sprintf(buf,fmt,n);
  2456. X    xlputstr(fptr,buf);
  2457. X}
  2458. X
  2459. X/* putflonum - output a flonum */
  2460. XLOCAL putflonum(fptr,n)
  2461. X  LVAL fptr; FLOTYPE n;
  2462. X{
  2463. X    unsigned char *fmt;
  2464. X    LVAL val;
  2465. X    fmt = ((val = getvalue(s_ffmt)) && stringp(val) ? getstring(val)
  2466. X                            : (unsigned char *)"%g");
  2467. X    sprintf(buf,fmt,n);
  2468. X    xlputstr(fptr,buf);
  2469. X}
  2470. X
  2471. X/* putchcode - output a character */
  2472. XLOCAL putchcode(fptr,ch,escflag)
  2473. X  LVAL fptr; int ch,escflag;
  2474. X{
  2475. X    if (escflag) {
  2476. X    switch (ch) {
  2477. X    case '\n':
  2478. X        xlputstr(fptr,"#\\Newline");
  2479. X        break;
  2480. X    case ' ':
  2481. X        xlputstr(fptr,"#\\Space");
  2482. X        break;
  2483. X    default:
  2484. X        sprintf(buf,"#\\%c",ch);
  2485. X        xlputstr(fptr,buf);
  2486. X        break;
  2487. X    }
  2488. X    }
  2489. X    else
  2490. X    xlputc(fptr,ch);
  2491. X}
  2492. X
  2493. X/* putoct - output an octal byte value */
  2494. XLOCAL putoct(fptr,n)
  2495. X  LVAL fptr; int n;
  2496. X{
  2497. X    sprintf(buf,"%03o",n);
  2498. X    xlputstr(fptr,buf);
  2499. X}
  2500. SHAR_EOF
  2501. if test 7244 -ne "`wc -c 'xlprin.c'`"
  2502. then
  2503.     echo shar: error transmitting "'xlprin.c'" '(should have been 7244 characters)'
  2504. fi
  2505. #    End of shell archive
  2506. exit 0
  2507. -- 
  2508. Gary Murphy                   uunet!mitel!sce!cognos!garym
  2509.                               (garym%cognos.uucp@uunet.uu.net)
  2510. (613) 738-1338 x5537          Cognos Inc. P.O. Box 9707 Ottawa K1G 3N3
  2511. "There are many things which do not concern the process" - Joan of Arc
  2512.  
  2513.